home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / 3Dfx / DEMOS / RAY.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-29  |  18.1 KB  |  863 lines

  1. /*
  2.  * This program is under the GNU GPL.
  3.  * Use at your own risk.
  4.  *
  5.  * written by David Bucciarelli (tech.hmw@plus.it)
  6.  *            Humanware s.r.l.
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12.  
  13. #ifdef WIN32
  14. #include <windows.h>
  15. #endif
  16.  
  17. #include <GL/glut.h>
  18.  
  19. #ifdef XMESA
  20. #include "GL/xmesa.h"
  21. static int fullscreen=1;
  22. #endif
  23.  
  24. static int WIDTH=640;
  25. static int HEIGHT=480;
  26.  
  27. #define FRAME 50
  28.  
  29. #define BASESIZE 7.5f
  30. #define SPHERE_RADIUS 0.75f
  31.  
  32. #define TEX_CHECK_WIDTH 256
  33. #define TEX_CHECK_HEIGHT 256
  34. #define TEX_CHECK_SLOT_SIZE (TEX_CHECK_HEIGHT/16)
  35. #define TEX_CHECK_NUMSLOT (TEX_CHECK_HEIGHT/TEX_CHECK_SLOT_SIZE)
  36.  
  37. #define TEX_REFLECT_WIDTH 256
  38. #define TEX_REFLECT_HEIGHT 256
  39. #define TEX_REFLECT_SLOT_SIZE (TEX_REFLECT_HEIGHT/16)
  40. #define TEX_REFLECT_NUMSLOT (TEX_REFLECT_HEIGHT/TEX_REFLECT_SLOT_SIZE)
  41.  
  42. #ifndef M_PI
  43. #define M_PI 3.1415926535
  44. #endif
  45.  
  46. #define EPSILON 0.0001
  47.  
  48. #define clamp255(a)  ( (a)<(0.0f) ? (0.0f) : ((a)>(255.0f) ? (255.0f) : (a)) )
  49.  
  50. #define fabs(x) ((x)<0.0f?-(x):(x))
  51.  
  52. #define vequ(a,b) { (a)[0]=(b)[0]; (a)[1]=(b)[1]; (a)[2]=(b)[2]; }
  53. #define vsub(a,b,c) { (a)[0]=(b)[0]-(c)[0]; (a)[1]=(b)[1]-(c)[1]; (a)[2]=(b)[2]-(c)[2]; }
  54. #define    dprod(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
  55. #define vnormalize(a,b) { \
  56.   register float m_norm; \
  57.   m_norm=sqrt((double)dprod((a),(a))); \
  58.   (a)[0] /=m_norm; \
  59.   (a)[1] /=m_norm; \
  60.   (a)[2] /=m_norm; }
  61.  
  62. static GLubyte checkmap[TEX_CHECK_HEIGHT][TEX_CHECK_WIDTH][3];
  63. static GLuint checkid;
  64. static int checkmap_currentslot=0;
  65.  
  66. static GLubyte reflectmap[TEX_REFLECT_HEIGHT][TEX_REFLECT_WIDTH][3];
  67. static GLuint reflectid;
  68. static int reflectmap_currentslot=0;
  69.  
  70. static GLuint lightdlist;
  71. static GLuint objdlist;
  72.  
  73. static float lightpos[3]={2.1,2.1,2.8};
  74. static float objpos[3]={0.0,0.0,1.0};
  75.  
  76. static float sphere_pos[TEX_CHECK_HEIGHT][TEX_REFLECT_WIDTH][3];
  77.  
  78. static int win=0;
  79.  
  80. static float fogcolor[4]={0.05,0.05,0.05,1.0};
  81.  
  82. static float obs[3]={7.0,0.0,2.0};
  83. static float dir[3];
  84. static float v=0.0;
  85. static float alpha=-90.0;
  86. static float beta=90.0;
  87.  
  88. static int fog=1;
  89. static int bfcull=1;
  90. static int poutline=0;
  91. static int help=1;
  92. static int showcheckmap=1;
  93. static int showreflectmap=1;
  94. static int joyavailable=0;
  95. static int joyactive=0;
  96.  
  97. static float gettime(void)
  98. {
  99.   static float told=0.0f;
  100.   float tnew,ris;
  101.  
  102.   tnew=glutGet(GLUT_ELAPSED_TIME);
  103.  
  104.   ris=tnew-told;
  105.  
  106.   told=tnew;
  107.  
  108.   return ris/1000.0;
  109. }
  110.  
  111. static void calcposobs(void)
  112. {
  113.   dir[0]=sin(alpha*M_PI/180.0);
  114.   dir[1]=cos(alpha*M_PI/180.0)*sin(beta*M_PI/180.0);
  115.   dir[2]=cos(beta*M_PI/180.0);
  116.  
  117.   obs[0]+=v*dir[0];
  118.   obs[1]+=v*dir[1];
  119.   obs[2]+=v*dir[2];
  120. }
  121.  
  122. static void special(int k, int x, int y)
  123. {
  124.   switch(k) {
  125.   case GLUT_KEY_LEFT:
  126.     alpha-=2.0;
  127.     break;
  128.   case GLUT_KEY_RIGHT:
  129.     alpha+=2.0;
  130.     break;
  131.   case GLUT_KEY_DOWN:
  132.     beta-=2.0;
  133.     break;
  134.   case GLUT_KEY_UP:
  135.     beta+=2.0;
  136.     break;
  137.   }
  138. }
  139.  
  140. static void key(unsigned char k, int x, int y)
  141. {
  142.   switch(k) {
  143.   case 27:
  144.     exit(0);
  145.     break;
  146.  
  147.   case 's':
  148.     lightpos[1]-=0.1;
  149.     break;
  150.   case 'd':
  151.     lightpos[1]+=0.1;
  152.     break;
  153.   case 'e':
  154.     lightpos[0]-=0.1;
  155.     break;
  156.   case 'x':
  157.     lightpos[0]+=0.1;
  158.     break;
  159.   case 'w':
  160.     lightpos[2]-=0.1;
  161.     break;
  162.   case 'r':
  163.     lightpos[2]+=0.1;
  164.     break;
  165.  
  166.   case 'j':
  167.     objpos[1]-=0.1;
  168.     break;
  169.   case 'k':
  170.     objpos[1]+=0.1;
  171.     break;
  172.   case 'i':
  173.     objpos[0]-=0.1;
  174.     break;
  175.   case 'm':
  176.     objpos[0]+=0.1;
  177.     break;
  178.   case 'u':
  179.     objpos[2]-=0.1;
  180.     break;
  181.   case 'o':
  182.     objpos[2]+=0.1;
  183.     break;
  184.  
  185.   case 'a':
  186.     v+=0.005;
  187.     break;
  188.   case 'z':
  189.     v-=0.005;
  190.     break;
  191.  
  192.   case 'g':
  193.     joyactive=(!joyactive);
  194.     break;
  195.   case 'h':
  196.     help=(!help);
  197.     break;
  198.   case 'f':
  199.     fog=(!fog);
  200.     break;
  201.  
  202.   case '1':
  203.     showcheckmap=(!showcheckmap);
  204.     break;
  205.   case '2':
  206.     showreflectmap=(!showreflectmap);
  207.     break;
  208.  
  209.   case 'b':
  210.     if(bfcull) {
  211.       glDisable(GL_CULL_FACE);
  212.       bfcull=0;
  213.     } else {
  214.       glEnable(GL_CULL_FACE);
  215.       bfcull=1;
  216.     }
  217.     break;
  218.   case 'p':
  219.     if(poutline) {
  220.       glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
  221.       poutline=0;
  222.     }    else {
  223.       glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
  224.       poutline=1;
  225.     }
  226.     break;
  227. #ifdef XMESA
  228.   case ' ':
  229.     XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
  230.     fullscreen=(!fullscreen);
  231.     break;
  232. #endif
  233.   }
  234. }
  235.  
  236. static void reshape(int w, int h) 
  237. {
  238.   WIDTH=w;
  239.   HEIGHT=h;
  240.   glViewport(0,0,w,h);
  241.   glMatrixMode(GL_PROJECTION);
  242.   glLoadIdentity();
  243.   gluPerspective(45.0,w/(float)h,0.8,40.0);
  244.   glMatrixMode(GL_MODELVIEW);
  245.   glLoadIdentity();
  246. }
  247.  
  248. static void printstring(void *font, char *string)
  249. {
  250.   int len,i;
  251.  
  252.   len=(int)strlen(string);
  253.   for(i=0;i<len;i++)
  254.     glutBitmapCharacter(font,string[i]);
  255. }
  256.  
  257. static void printhelp(void)
  258. {
  259.   glEnable(GL_BLEND);
  260.   glColor4f(0.5,0.5,0.5,0.5);
  261.   glRecti(40,40,600,440);
  262.   glDisable(GL_BLEND);
  263.  
  264.   glColor3f(0.0,0.0,1.0);
  265.   glRasterPos2i(300,420);
  266.   printstring(GLUT_BITMAP_HELVETICA_18,"Help");
  267.  
  268.   glRasterPos2i(60,390);
  269.   printstring(GLUT_BITMAP_HELVETICA_12,"h - Togle Help");
  270.   glRasterPos2i(60,370);
  271.   printstring(GLUT_BITMAP_HELVETICA_12,"f - Togle Fog");
  272.   glRasterPos2i(60,350);
  273.   printstring(GLUT_BITMAP_HELVETICA_12,"b - Togle Back face culling");
  274.   glRasterPos2i(60,330);
  275.   printstring(GLUT_BITMAP_HELVETICA_12,"p - Togle Wire frame");
  276.   glRasterPos2i(60,310);
  277.   printstring(GLUT_BITMAP_HELVETICA_12,"Arrow Keys - Rotate");
  278.   glRasterPos2i(60,290);
  279.   printstring(GLUT_BITMAP_HELVETICA_12,"a - Increase velocity");
  280.   glRasterPos2i(60,270);
  281.   printstring(GLUT_BITMAP_HELVETICA_12,"z - Decrease velocity");
  282.  
  283.   glRasterPos2i(60,250);
  284.   if(joyavailable)
  285.     printstring(GLUT_BITMAP_HELVETICA_12,"j - Togle jostick control (Joystick control available)");
  286.   else
  287.     printstring(GLUT_BITMAP_HELVETICA_12,"(No Joystick control available)");
  288.  
  289.   glRasterPos2i(60,230);
  290.   printstring(GLUT_BITMAP_HELVETICA_12,"To move the light source: s - left,  d - right,  e - far,  x - near,  w - down r - up");
  291.   glRasterPos2i(60,210);
  292.   printstring(GLUT_BITMAP_HELVETICA_12,"To move the mirror sphere: j - left,  k - right,  i - far,  m - near,  u - down o - up");
  293.  
  294.   glRasterPos2i(60,190);
  295.   printstring(GLUT_BITMAP_HELVETICA_12,"1 - Togle the plane texture map window");
  296.  
  297.   glRasterPos2i(60,170);
  298.   printstring(GLUT_BITMAP_HELVETICA_12,"2 - Togle the sphere texture map window");
  299. }
  300.  
  301. static GLboolean seelight(float p[3],float dir[3])
  302. {
  303.   float c[3],b,a,d,t,dist[3];
  304.  
  305.   vsub(c,p,objpos);
  306.   b=-dprod(c,dir);
  307.   a=dprod(c,c)-SPHERE_RADIUS*SPHERE_RADIUS;
  308.  
  309.   if((d=b*b-a)<0.0 || (b<0.0 && a>0.0))
  310.     return GL_FALSE;
  311.  
  312.   d=sqrt(d);
  313.  
  314.   t=b-d;
  315.  
  316.   if(t<EPSILON) {
  317.     t=b+d;
  318.     if(t<EPSILON)
  319.       return GL_FALSE;
  320.   }
  321.  
  322.   vsub(dist,lightpos,p);
  323.   if(dprod(dist,dist)<t*t)
  324.       return GL_FALSE;
  325.  
  326.   return GL_TRUE;
  327. }
  328.  
  329. static int colorcheckmap(float ppos[3], float c[3])
  330. {
  331.   static float norm[3]={0.0f,0.0f,1.0f};
  332.   float ldir[3],vdir[3],h[3],dfact,kfact,r,g,b;
  333.   int x,y;
  334.  
  335.   x=(int)((ppos[0]+BASESIZE/2)*(10.0f/BASESIZE));
  336.   if((x<0) || (x>10))
  337.     return GL_FALSE;
  338.  
  339.   y=(int)((ppos[1]+BASESIZE/2)*(10.0f/BASESIZE));
  340.   if((y<0) || (y>10))
  341.     return GL_FALSE;
  342.  
  343.   r=255.0f;
  344.   if(y & 1) {
  345.     if(x & 1)
  346.       g=255.0f;
  347.     else
  348.       g=0.0f;
  349.   } else {
  350.     if(x & 1)
  351.       g=0.0f;
  352.     else
  353.       g=255.0f;
  354.   }
  355.   b=0.0f;
  356.  
  357.   vsub(ldir,lightpos,ppos);
  358.   vnormalize(ldir,ldir);
  359.  
  360.   if(seelight(ppos,ldir)) {
  361.     c[0]=r*0.05f;
  362.     c[1]=g*0.05f;
  363.     c[2]=b*0.05f;
  364.  
  365.     return GL_TRUE;
  366.   }
  367.  
  368.   dfact=dprod(ldir,norm);
  369.   if(dfact<0.0f)
  370.     dfact=0.0f;
  371.  
  372.   vsub(vdir,obs,ppos);
  373.   vnormalize(vdir,vdir);
  374.   h[0]=0.5f*(vdir[0]+ldir[0]);
  375.   h[1]=0.5f*(vdir[1]+ldir[1]);
  376.   h[2]=0.5f*(vdir[2]+ldir[2]);
  377.   kfact=dprod(h,norm);
  378.   kfact=kfact*kfact*kfact*kfact*kfact*kfact*kfact*7.0f*255.0f;
  379.  
  380.   r=r*dfact+kfact;
  381.   g=g*dfact+kfact;
  382.   b=b*dfact+kfact;
  383.   
  384.   c[0]=clamp255(r);
  385.   c[1]=clamp255(g);
  386.   c[2]=clamp255(b);
  387.  
  388.   return GL_TRUE;
  389. }
  390.  
  391. static void updatecheckmap(int slot)
  392. {
  393.   float c[3],ppos[3];
  394.   int x,y;
  395.  
  396.   glBindTexture(GL_TEXTURE_2D,checkid);
  397.  
  398.   ppos[2]=0.0f;
  399.   for(y=slot*TEX_CHECK_SLOT_SIZE;y<(slot+1)*TEX_CHECK_SLOT_SIZE;y++) {
  400.     ppos[1]=(y/(float)TEX_CHECK_HEIGHT)*BASESIZE-BASESIZE/2;
  401.  
  402.     for(x=0;x<TEX_CHECK_WIDTH;x++) {
  403.       ppos[0]=(x/(float)TEX_CHECK_WIDTH)*BASESIZE-BASESIZE/2;
  404.  
  405.       colorcheckmap(ppos,c);
  406.       checkmap[y][x][0]=(GLubyte)c[0];
  407.       checkmap[y][x][1]=(GLubyte)c[1];
  408.       checkmap[y][x][2]=(GLubyte)c[2];
  409.     }
  410.   }
  411.  
  412.   glTexSubImage2D(GL_TEXTURE_2D,0,0,slot*TEX_CHECK_SLOT_SIZE,TEX_CHECK_WIDTH,
  413.           TEX_CHECK_SLOT_SIZE,GL_RGB,GL_UNSIGNED_BYTE,
  414.           &checkmap[slot*TEX_CHECK_SLOT_SIZE][0][0]);
  415.  
  416. }
  417.  
  418. static void updatereflectmap(int slot)
  419. {
  420.   float rf,r,g,b,t,dfact,kfact,rdir[3];
  421.   float rcol[3],ppos[3],norm[3],ldir[3],h[3],vdir[3],planepos[3];
  422.   int x,y;
  423.  
  424.   glBindTexture(GL_TEXTURE_2D,reflectid);
  425.  
  426.   for(y=slot*TEX_REFLECT_SLOT_SIZE;y<(slot+1)*TEX_REFLECT_SLOT_SIZE;y++)
  427.     for(x=0;x<TEX_REFLECT_WIDTH;x++) {
  428.       ppos[0]=sphere_pos[y][x][0]+objpos[0];
  429.       ppos[1]=sphere_pos[y][x][1]+objpos[1];
  430.       ppos[2]=sphere_pos[y][x][2]+objpos[2];
  431.  
  432.       vsub(norm,ppos,objpos);
  433.       vnormalize(norm,norm);
  434.  
  435.       vsub(ldir,lightpos,ppos);
  436.       vnormalize(ldir,ldir);
  437.       vsub(vdir,obs,ppos);
  438.       vnormalize(vdir,vdir);
  439.  
  440.       rf=2.0f*dprod(norm,vdir);
  441.       if(rf>EPSILON) {
  442.     rdir[0]=rf*norm[0]-vdir[0];
  443.     rdir[1]=rf*norm[1]-vdir[1];
  444.     rdir[2]=rf*norm[2]-vdir[2];
  445.  
  446.     t=-objpos[2]/rdir[2];
  447.  
  448.     if(t>EPSILON) {
  449.       planepos[0]=objpos[0]+t*rdir[0];
  450.       planepos[1]=objpos[1]+t*rdir[1];
  451.       planepos[2]=0.0f;
  452.       
  453.       if(!colorcheckmap(planepos,rcol))
  454.         rcol[0]=rcol[1]=rcol[2]=0.0f;
  455.     } else
  456.       rcol[0]=rcol[1]=rcol[2]=0.0f;
  457.       } else
  458.     rcol[0]=rcol[1]=rcol[2]=0.0f;
  459.  
  460.       dfact=0.1f*dprod(ldir,norm);
  461.  
  462.       if(dfact<0.0f) {
  463.     dfact=0.0f;
  464.     kfact=0.0f;
  465.       } else {
  466.     h[0]=0.5f*(vdir[0]+ldir[0]);
  467.     h[1]=0.5f*(vdir[1]+ldir[1]);
  468.     h[2]=0.5f*(vdir[2]+ldir[2]);
  469.     kfact=dprod(h,norm);
  470.     kfact*=kfact;
  471.     kfact*=kfact;
  472.     kfact*=kfact;
  473.     kfact*=kfact;
  474.     kfact*=10.0f;
  475.       }
  476.  
  477.       r=dfact+kfact;
  478.       g=dfact+kfact;
  479.       b=dfact+kfact;
  480.  
  481.       r*=255.0f;
  482.       g*=255.0f;
  483.       b*=255.0f;
  484.  
  485.       r+=rcol[0];
  486.       g+=rcol[1];
  487.       b+=rcol[2];
  488.  
  489.       r=clamp255(r);
  490.       g=clamp255(g);
  491.       b=clamp255(b);
  492.  
  493.       reflectmap[y][x][0]=(GLubyte)r;
  494.       reflectmap[y][x][1]=(GLubyte)g;
  495.       reflectmap[y][x][2]=(GLubyte)b;
  496.     }
  497.  
  498.   glTexSubImage2D(GL_TEXTURE_2D,0,0,slot*TEX_REFLECT_SLOT_SIZE,TEX_REFLECT_WIDTH,
  499.           TEX_REFLECT_SLOT_SIZE,GL_RGB,GL_UNSIGNED_BYTE,
  500.           &reflectmap[slot*TEX_REFLECT_SLOT_SIZE][0][0]);
  501. }
  502.  
  503. static void drawbase(void)
  504. {
  505.   glColor3f(0.0,0.0,0.0);
  506.   glBindTexture(GL_TEXTURE_2D,checkid);
  507.   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
  508.  
  509.   glBegin(GL_QUADS);
  510.   glTexCoord2f(0.0f,0.0f);
  511.   glVertex3f(-BASESIZE/2.0f,-BASESIZE/2.0f,0.0f);
  512.  
  513.   glTexCoord2f(1.0f,0.0f);
  514.   glVertex3f(BASESIZE/2.0f,-BASESIZE/2.0f,0.0f);
  515.  
  516.   glTexCoord2f(1.0f,1.0f);
  517.   glVertex3f(BASESIZE/2.0f,BASESIZE/2.0f,0.0f);
  518.  
  519.   glTexCoord2f(0.0f,1.0f);
  520.   glVertex3f(-BASESIZE/2.0f,BASESIZE/2.0f,0.0f);
  521.  
  522.   glEnd();
  523. }
  524.  
  525. static void drawobj(void)
  526. {
  527.   glColor3f(0.0,0.0,0.0);
  528.   glBindTexture(GL_TEXTURE_2D,reflectid);
  529.   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
  530.  
  531.   glPushMatrix();
  532.   glTranslatef(objpos[0],objpos[1],objpos[2]);
  533.   glCallList(objdlist);
  534.   glPopMatrix();
  535. }
  536.  
  537. static void dojoy(void)
  538. {
  539. #ifdef WIN32
  540.   static UINT max[2]={0,0};
  541.   static UINT min[2]={0xffffffff,0xffffffff},center[2];
  542.   MMRESULT res;
  543.   JOYINFO joy;
  544.  
  545.   res=joyGetPos(JOYSTICKID1,&joy);
  546.  
  547.   if(res==JOYERR_NOERROR) {
  548.     joyavailable=1;
  549.  
  550.     if(max[0]<joy.wXpos)
  551.       max[0]=joy.wXpos;
  552.     if(min[0]>joy.wXpos)
  553.       min[0]=joy.wXpos;
  554.     center[0]=(max[0]+min[0])/2;
  555.  
  556.     if(max[1]<joy.wYpos)
  557.       max[1]=joy.wYpos;
  558.     if(min[1]>joy.wYpos)
  559.       min[1]=joy.wYpos;
  560.     center[1]=(max[1]+min[1])/2;
  561.  
  562.     if(joyactive) {
  563.       if(fabs(center[0]-(float)joy.wXpos)>0.1*(max[0]-min[0]))
  564.     alpha-=2.5*(center[0]-(float)joy.wXpos)/(max[0]-min[0]);
  565.       if(fabs(center[1]-(float)joy.wYpos)>0.1*(max[1]-min[1]))
  566.     beta+=2.5*(center[1]-(float)joy.wYpos)/(max[1]-min[1]);
  567.  
  568.       if(joy.wButtons & JOY_BUTTON1)
  569.     v+=0.005;
  570.       if(joy.wButtons & JOY_BUTTON2)
  571.     v-=0.005;
  572.     }
  573.   } else
  574.     joyavailable=0;
  575. #endif
  576. }
  577.  
  578. static void updatemaps(void)
  579. {
  580.   updatecheckmap(checkmap_currentslot);
  581.   checkmap_currentslot=(checkmap_currentslot+1) % TEX_CHECK_NUMSLOT;
  582.  
  583.   updatereflectmap(reflectmap_currentslot);
  584.   reflectmap_currentslot=(reflectmap_currentslot+1) % TEX_REFLECT_NUMSLOT;
  585. }
  586.  
  587. static void draw(void)
  588. {
  589.   static int count=0;
  590.   static char frbuf[80];
  591.   float fr;
  592.  
  593.   dojoy();
  594.  
  595.   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  596.  
  597.   glEnable(GL_TEXTURE_2D);
  598.   glEnable(GL_DEPTH_TEST);
  599.   if(fog)
  600.     glEnable(GL_FOG);
  601.   else
  602.     glDisable(GL_FOG);
  603.  
  604.   glPushMatrix();
  605.   calcposobs();
  606.  
  607.   gluLookAt(obs[0],obs[1],obs[2],
  608.         obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2],
  609.         0.0,0.0,1.0);
  610.  
  611.   drawbase();
  612.   drawobj();
  613.  
  614.   glColor3f(1.0,1.0,1.0);
  615.   glDisable(GL_TEXTURE_2D);
  616.  
  617.   glPushMatrix();
  618.   glTranslatef(lightpos[0],lightpos[1],lightpos[2]);
  619.   glCallList(lightdlist);
  620.   glPopMatrix();
  621.  
  622.   glPopMatrix();
  623.   
  624.   if((count % FRAME)==0) {
  625.     fr=gettime();
  626.     sprintf(frbuf,"Frame rate: %f",FRAME/fr);
  627.   }
  628.  
  629.   glDisable(GL_DEPTH_TEST);
  630.   glDisable(GL_FOG);
  631.  
  632.   glMatrixMode(GL_PROJECTION);
  633.   glPushMatrix();
  634.   glLoadIdentity();
  635.   glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
  636.   glMatrixMode(GL_MODELVIEW);
  637.  
  638.   glColor3f(0.0f,0.3f,1.0f);
  639.  
  640.   if(showcheckmap) {
  641.     glEnable(GL_TEXTURE_2D);
  642.     glBindTexture(GL_TEXTURE_2D,checkid);
  643.     glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
  644.  
  645.     glBegin(GL_QUADS);
  646.     glTexCoord2f(1.0f,0.0f);
  647.     glVertex2i(10,30);
  648.     glTexCoord2f(1.0f,1.0f);
  649.     glVertex2i(10+90,30);
  650.     glTexCoord2f(0.0f,1.0f);
  651.     glVertex2i(10+90,30+90);
  652.     glTexCoord2f(0.0f,0.0f);
  653.     glVertex2i(10,30+90);
  654.     glEnd();
  655.  
  656.     glDisable(GL_TEXTURE_2D);
  657.     glBegin(GL_LINE_LOOP);
  658.     glVertex2i(10,30);
  659.     glVertex2i(10+90,30);
  660.     glVertex2i(10+90,30+90);
  661.     glVertex2i(10,30+90);
  662.     glEnd();
  663.     glRasterPos2i(105,65);
  664.     printstring(GLUT_BITMAP_HELVETICA_18,"Plane Texture Map");
  665.   }
  666.  
  667.   if(showreflectmap) {
  668.     glEnable(GL_TEXTURE_2D);
  669.     glBindTexture(GL_TEXTURE_2D,reflectid);
  670.     glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
  671.  
  672.     glBegin(GL_QUADS);
  673.     glTexCoord2f(1.0f,0.0f);
  674.     glVertex2i(540,30);
  675.     glTexCoord2f(1.0f,1.0f);
  676.     glVertex2i(540+90,30);
  677.     glTexCoord2f(0.0f,1.0f);
  678.     glVertex2i(540+90,30+90);
  679.     glTexCoord2f(0.0f,0.0f);
  680.     glVertex2i(540,30+90);
  681.     glEnd();
  682.  
  683.     glDisable(GL_TEXTURE_2D);
  684.     glBegin(GL_LINE_LOOP);
  685.     glVertex2i(540,30);
  686.     glVertex2i(540+90,30);
  687.     glVertex2i(540+90,30+90);
  688.     glVertex2i(540,30+90);
  689.     glEnd();
  690.     glRasterPos2i(360,65);
  691.     printstring(GLUT_BITMAP_HELVETICA_18,"Sphere Texture Map");
  692.   }
  693.  
  694.   glDisable(GL_TEXTURE_2D);
  695.  
  696.   glRasterPos2i(10,10);
  697.   printstring(GLUT_BITMAP_HELVETICA_18,frbuf);
  698.   glRasterPos2i(360,470);
  699.   printstring(GLUT_BITMAP_HELVETICA_10,"Ray V1.0 Written by David Bucciarelli (tech.hmw@plus.it)");
  700.  
  701.   if(help)
  702.     printhelp();
  703.  
  704.   glMatrixMode(GL_PROJECTION);
  705.   glPopMatrix();
  706.   glMatrixMode(GL_MODELVIEW);
  707.  
  708.   updatemaps();
  709.  
  710.   glutSwapBuffers();
  711.  
  712.   count++;
  713. }
  714.  
  715. static void inittextures(void)
  716. {
  717.   int y;
  718.  
  719.   glGenTextures(1,&checkid);
  720.   glBindTexture(GL_TEXTURE_2D,checkid);
  721.  
  722.   for(y=0;y<TEX_CHECK_NUMSLOT;y++)
  723.     updatecheckmap(y);
  724.  
  725.   glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  726.   glTexImage2D(GL_TEXTURE_2D,0,3,TEX_CHECK_WIDTH,TEX_CHECK_HEIGHT,
  727.            0,GL_RGB,GL_UNSIGNED_BYTE,checkmap);
  728.  
  729.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
  730.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
  731.   
  732.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  733.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  734.  
  735.   glGenTextures(1,&reflectid);
  736.   glBindTexture(GL_TEXTURE_2D,reflectid);
  737.  
  738.   for(y=0;y<TEX_REFLECT_NUMSLOT;y++)
  739.     updatereflectmap(y);
  740.  
  741.   glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  742.   glTexImage2D(GL_TEXTURE_2D,0,3,TEX_REFLECT_WIDTH,TEX_REFLECT_HEIGHT,
  743.            0,GL_RGB,GL_UNSIGNED_BYTE,reflectmap);
  744.  
  745.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
  746.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
  747.   
  748.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  749.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  750. }
  751.  
  752. static void initspherepos(void)
  753. {
  754.   float alpha,beta,sa,ca,sb,cb;
  755.   int x,y;
  756.  
  757.   for(y=0;y<TEX_REFLECT_HEIGHT;y++) {
  758.     beta=M_PI-y*(M_PI/TEX_REFLECT_HEIGHT);
  759.  
  760.     for(x=0;x<TEX_REFLECT_WIDTH;x++) {
  761.       alpha=-x*(2.0f*M_PI/TEX_REFLECT_WIDTH);
  762.  
  763.       sa=sin(alpha);
  764.       ca=cos(alpha);
  765.  
  766.       sb=sin(beta);
  767.       cb=cos(beta);
  768.  
  769.       sphere_pos[y][x][0]=SPHERE_RADIUS*sa*sb;
  770.       sphere_pos[y][x][1]=SPHERE_RADIUS*ca*sb;
  771.       sphere_pos[y][x][2]=SPHERE_RADIUS*cb;
  772.     }
  773.   }
  774. }
  775.  
  776. static void initdlists(void)
  777. {
  778.   GLUquadricObj *obj;
  779.  
  780.   obj=gluNewQuadric();
  781.  
  782.   lightdlist=glGenLists(1);
  783.   glNewList(lightdlist,GL_COMPILE);
  784.   gluQuadricDrawStyle(obj,GLU_FILL);
  785.   gluQuadricNormals(obj,GLU_NONE);
  786.   gluQuadricTexture(obj,GL_TRUE);
  787.   gluSphere(obj,0.25f,6,6);
  788.   glEndList();
  789.  
  790.   objdlist=glGenLists(1);
  791.   glNewList(objdlist,GL_COMPILE);
  792.   gluQuadricDrawStyle(obj,GLU_FILL);
  793.   gluQuadricNormals(obj,GLU_NONE);
  794.   gluQuadricTexture(obj,GL_TRUE);
  795.   gluSphere(obj,SPHERE_RADIUS,16,16);
  796.   glEndList();
  797. }
  798.  
  799. int main(int ac, char **av)
  800. {
  801.   fprintf(stderr,"Ray V1.0\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
  802.  
  803.   /*
  804.     if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
  805.     fprintf(stderr,"Error setting the process class.\n");
  806.     return 0;
  807.     }
  808.  
  809.     if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
  810.     fprintf(stderr,"Error setting the process priority.\n");
  811.     return 0;
  812.     }
  813.     */
  814.  
  815.   glutInitWindowPosition(0,0);
  816.   glutInitWindowSize(WIDTH,HEIGHT);
  817.   glutInit(&ac,av);
  818.  
  819.   glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
  820.  
  821.   if(!(win=glutCreateWindow("Ray"))) {
  822.     fprintf(stderr,"Error, couldn't open window\n");
  823.     return -1;
  824.   }
  825.  
  826.   reshape(WIDTH,HEIGHT);
  827.  
  828.   glShadeModel(GL_FLAT);
  829.   glEnable(GL_DEPTH_TEST);
  830.   glDepthFunc(GL_LEQUAL);
  831.   glEnable(GL_CULL_FACE);
  832.   glEnable(GL_TEXTURE_2D);
  833.   glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  834.  
  835.   glEnable(GL_FOG);
  836.   glFogi(GL_FOG_MODE,GL_EXP2);
  837.   glFogfv(GL_FOG_COLOR,fogcolor);
  838.  
  839.   glFogf(GL_FOG_DENSITY,0.01);
  840. #ifdef FX
  841.   glHint(GL_FOG_HINT,GL_NICEST);
  842. #endif
  843.  
  844.   calcposobs();
  845.  
  846.   initspherepos();
  847.  
  848.   inittextures();
  849.   initdlists();
  850.  
  851.   glClearColor(fogcolor[0],fogcolor[1],fogcolor[2],fogcolor[3]);
  852.  
  853.   glutReshapeFunc(reshape);
  854.   glutDisplayFunc(draw);
  855.   glutKeyboardFunc(key);
  856.   glutSpecialFunc(special);
  857.   glutIdleFunc(draw);
  858.  
  859.   glutMainLoop();
  860.  
  861.   return 0;
  862. }
  863.